import {
	SERVICEID,
	NOTIFYID,
	WRITEID,
	BLUETOOTH_MESSAGE,
	hexStringToArrayBuffer,
	sleep,
	getBufferArrayBy20,
	arrayBufferToHexString,
	filterDevices,
} from "./utils.js"

import {
	$currentRoute,
	getNowTime
} from "@/utils/utils.js"
import vm from "@/main.js"

import md5 from "@/utils/md5.js"

let blueToothSearchTimer = '';
let isNormalDiscoveryStatus = false;
let notifyTimerId = 0;
let isBluetoothDiscovery = false; //判断是否搜索过蓝牙，如果搜索的有设备，则直接进行连接，不再进行再次搜索 

export let showModalUtil = function(content, callback = function() {}, showCancel = false, confirmText = "确定") {
	vm.$store.commit("setBluetoothContent", ''); //如果提示了失败，则重置了空，动画不在显示
	//如果当前页面是验证页面，并且没有执行定时器则需要提示,只有在验证页面并且点了验证按钮才提示信息
	if ($currentRoute() == "pagesMy/views/deviceVerify" && !vm.$store.state.isOpenTimer) {
		uni.showToast({
			title: content,
			icon: "none"
		})
	}
}

//正常蓝牙流程开始 isOpenTimer 是否开启蓝牙定时器
export let bluetoothStart = (isOpenTimer = true) => {
	vm.$store.commit("setIsOpenTimer", isOpenTimer);
	getBluetoothAdapterState();
	//清除定时器
	if (!vm.$validatenull(vm.$store.state.blueConnectTimer)) {
		clearInterval(vm.$store.state.blueConnectTimer);
	}
	if (isOpenTimer) {
		setBlueConnectTimer();
	}

}
export let setBlueConnectTimer = () => {
	let blueConnectTimer = setInterval(() => {
		//console.log("定时器检测到的蓝牙连接状态",vm.isConnected)
		//3s定时去检测蓝牙并连接蓝牙
		if (!vm.$store.state.isConnected) {
			bluetoothStart();
		}
	}, 15000);
	vm.$store.commit("setBlueConnectTimer", blueConnectTimer)
}

export let onBluetoothAdapterStateChange = () => {
	//如果蓝牙打开-关闭-再打开-监听不到？
	uni.onBluetoothAdapterStateChange(async (res) => {
		bluetoothExecByAdapterStatus(res);
	})
}

//根据蓝牙适配器的状态、是否正在搜索设备执行不同的操作流程
export let bluetoothExecByAdapterStatus = (res) => {
	if (!res.available) {
		showModalUtil("蓝牙适配器不可用，请打开蓝牙");
	} else {
		if (!res.discovering && !isNormalDiscoveryStatus) { // 防止正常停止搜索的时候会触发这个条件
			//如果前面已经搜索过蓝牙，则不需要再次搜索
			if (isBluetoothDiscovery) {
				getBluetoothDevices();
			} else {
				startAndStopbluetoothDevicesDiscovery();
			}
		}

	}

}

//获取在蓝牙模块生效期间所有已发现的蓝牙设备。包括已经和本机处于连接状态的设备
export let getBluetoothDevices = () => {
	uni.getBluetoothDevices({
		success(res) {
			let devices = res.devices;
			let devicesList = filterDevices(res.devices, vm.$store.state.blueCurrentToConnectDevice);
			if (devicesList.length > 0) {
				vm.$store.commit('setBluetoothDevice', devicesList[0]);
				createBLEConnection(devicesList[0])
			} else {
				startAndStopbluetoothDevicesDiscovery();
			}
		}
	})
}


//打开蓝牙设备并监听蓝牙设备
export let openAndOnBluetoothAdapter = () => {
	vm.$store.commit("setBluetoothContent", vm.$store.state.isOpenTimer ? "" : "正在初始化蓝牙");
	uni.openBluetoothAdapter({
		success(res) {
			console.log("打开蓝牙适配器成功");
			startAndStopbluetoothDevicesDiscovery();
		},
		fail(res) {
			console.log("打开蓝牙设备器失败", res)
			console.log(res.errMsg == "openBluetoothAdapter:fail already opened")
			//蓝牙适配器已经打开
			if (res.errMsg == "openBluetoothAdapter:fail already opened") {
				startAndStopbluetoothDevicesDiscovery();
			} else {
				console.log("打开蓝牙适配器失败:", BLUETOOTH_MESSAGE[res.errCode]);
				showModalUtil("蓝牙适配器不可用，请打开蓝牙或微信APP开启蓝牙权限");
			}

		},
		complete() {
			onBluetoothAdapterStateChange();
		}

	})
}

//开始和停止蓝牙搜索
export let startAndStopbluetoothDevicesDiscovery = () => {
	//1、关闭蓝牙-杀掉进程，开启蓝牙不会重新连接，没有监听搜索到的设备
	onBluetoothDeviceFound();
	//2、接步骤1，再关闭，再开发蓝牙，连接成功，但是不会触发蓝牙连接
	onBLEConnectionStateChange();

	vm.$store.commit("setBluetoothContent", vm.$store.state.isOpenTimer ? "" : '正在搜索蓝牙设备');
	isBluetoothDiscovery = true;
	vm.$store.commit('setBluetoothDevice', {}); //清空
	//如果60s都还未搜索到蓝牙，提示未搜索到，提示蓝牙不在可搜索范围内，
	let timer = setTimeout(() => {
		clearTimeout(timer);
		//没有找到设备并且定时器还在
		if (vm.$validatenull(vm.$store.state.bluetoothDevice)) {
			showModalUtil('蓝牙不在可搜索范围内');
			stopBluetoothDevicesDiscovery();
		}
	}, 10000);
	blueToothSearchTimer = timer;
	uni.startBluetoothDevicesDiscovery({
		services: [], //添加了SERVICEID搜索不到蓝牙
		allowDuplicatesKey: true,
		powerLevel: 'high',
		success() {
			console.log("开始蓝牙搜索成功");
		},
		fail(res) {
			console.log(res);
			showModalUtil('开始蓝牙搜索失败');
			console.log("开始蓝牙搜索失败:", BLUETOOTH_MESSAGE[res.errCode]);
		}
	})
}


export let stopBluetoothDevicesDiscovery = () => {
	uni.stopBluetoothDevicesDiscovery({
		success() {
			console.log("停止蓝牙搜索成功");
		},
		fail(res) {
			console.log("停止蓝牙搜索失败:", BLUETOOTH_MESSAGE[res.errCode]);
		},
		complete() {
			isNormalDiscoveryStatus = true;
			setTimeout(() => {
				isNormalDiscoveryStatus = false;
			}, 1000)

		}
	})
}
//监听寻找到新设备的事件
export let onBluetoothDeviceFound = () => {
	uni.onBluetoothDeviceFound((res) => {
		//搜索到的蓝牙设备并唯一
		let devices = filterDevices(res.devices, vm.$store.state.blueCurrentToConnectDevice);
		if (devices.length) {
			console.log("搜索到的目标设备", devices)
			vm.$store.commit('setBluetoothDevice', devices[0])
			clearTimeout(blueToothSearchTimer);
			createBLEConnection(devices[0]);
			stopBluetoothDevicesDiscovery();
		}
	})
}

export let getBluetoothAdapterState = () => {
	uni.getBluetoothAdapterState({
		success(res) {
			bluetoothExecByAdapterStatus(res);
		},
		fail(res) {
			console.log("获取蓝牙适配器状态失败:", BLUETOOTH_MESSAGE[res.errCode]);
			openAndOnBluetoothAdapter();
			//showModalUtil('蓝牙适配器不可用，请打开蓝牙');
		}
	})
}

//ios必须要执行
let getBLEDeviceServices = (device) => {
	uni.getBLEDeviceServices({
		deviceId: device.deviceId,
		success(res) {
			console.log(`获取${device.deviceId}服务成功`, res);
			getBLEDeviceCharacteristics(device);
		},
		fail(res) {
			vm.$store.commit("setIsConnected", false);
			console.log(`获取${device.deviceId}服务失败:`, BLUETOOTH_MESSAGE[res.errCode]);
			getBLEDeviceCharacteristics(device);
		}
	})
}

export let createBLEConnection = (device) => {
	vm.$store.commit("setBluetoothContent", vm.$store.state.isOpenTimer ? "" : '正在连接蓝牙设备');

	//如果当前状态没有连接，只去连接蓝牙
	if (!vm.$store.state.isConnected && !vm.$validatenull(vm.$store.state.bluetoothDevice)) {
		uni.createBLEConnection({
			deviceId: device.deviceId,
			success(res) {
				console.log(`与蓝牙设备${device.name}创建连接成功`, res);
				vm.$store.commit("setIsConnected", true);
				getBLEDeviceServices(device);
			},
			fail(res) {
				console.log(res)
				showModalUtil("蓝牙连接失败，请重试！");
				if (res.errCode == 10001) return; //如果是蓝牙设配器没有打开，则直接退出连接
			}
		})
	}

}

//ios必须要执行
let getBLEDeviceCharacteristics = (device) => {
	uni.getBLEDeviceCharacteristics({
		deviceId: device.deviceId,
		serviceId: SERVICEID,
		success: function(res) {
			console.log(`获取${device.deviceId}特征值成功`, res);
			notifyAndOnBLECharacteristicValueChange(device);
		},
		fail: function(res) {
			vm.$store.commit("setIsConnected", false);
			console.log(`获取${device.deviceId}特征值失败`, res);
		},
	})
}

export let onBLEConnectionStateChange = () => {
	uni.onBLEConnectionStateChange((res) => {
		console.log("监听蓝牙是否断开", res);
		vm.$store.commit("setIsConnected", res.connected)
	})
}

//字符串转16进制
export const stringToHex = function(str) {
	var val = "";
	for (var i = 0; i < str.length; i++) {
		if (val == "") {
			val = str.charCodeAt(i).toString(16); //获取字符的Unicode码然后转16进制
		} else {
			val += str.charCodeAt(i).toString(16); //获取字符的Unicode码然后转16进制再拼接,中间用逗号隔开
		}
	}
	return val;
}


//获取下发的报文
export const getCommandPacket = function(type, ecuid, paramValue) {
	let timeStamp = parseInt(new Date().getTime() / 1000);
	let md5Code = "JDWARQ_mCLLoVQlPHgkixVj";
	let val = "";
	if (type == 1006) {
		val = `TBOX,CQCT,${type},${ecuid},${ser},${paramValue},${timeStamp},`;
	} else {
		val = `TBOX,CQCT,${type},${ecuid},${ser},${timeStamp},`;
	}
	let md5Value = md5(val + md5Code);
	let result = val + md5Value + `,TBOXEND`;
	console.log("下发的报文字符串", result);
	return stringToHex(result);
}


//十六进制转字符串
//54424F582C435143542C302C433031323330323230303030312C31322E30322C30312E33342C3836313139373036333333373638392C38393836303432383232313939303231333339322C31303633382E30343730452C323932382E383833374E2C302C302E30302C302C302E30302C302C302E302C31322E302C302C302E30303030302C302E302C302E302C302E302C39302C302E30303030302C322C50303536322C302E302C302E302C302C302E302C302E302C302C302C30302C2C2C313637383334333238342C33323131376431316630383539363132343033613532316136316165643533312C54424F58454E44
//54424f582c435143542c302c433031323330323230303030312c31322e30322c30312e33342c3836313139373036333333373638392c38393836303432383232313939303231333339322c31303633382e30343730452c323932382e383833374e2c302c302e30302c302c302e30302c302c302e302c31322e302c302c302e30303030302c302e302c302e302c302e302c39302c302e30303030302c322c50303536322c302e302c302e302c302c302e302c302e302c302c302c30302c2c2c313637383334333238342c33323131376431316630383539363132343033613532316136316165643533312c54424f58454e44
//'TBOX,CQCT,0,C012302200001,12.02,01.34,861197063337689,89860428221990213392,10638.0470E,2928.8837N,0,0.00,0,0.00,0,0.0,12.0,0,0.00000,0.0,0.0,0.0,90,0.00000,2,P0562,0.0,0.0,0,0.0,0.0,0,0,00,,,1678343284,32117d11f0859612403a521a61aed531,TBOXEND'
export const hexToStr = function(hex, encoding) {
	var trimedStr = hex.trim();
	var rawStr = trimedStr.substr(0, 2).toLowerCase() === "0x" ? trimedStr.substr(2) : trimedStr;
	var len = rawStr.length;

	var curCharCode;
	var resultStr = [];
	for (var i = 0; i < len; i = i + 2) {
		curCharCode = parseInt(rawStr.substr(i, 2), 16);
		resultStr.push(curCharCode);
	}
	var val = "";
	var arr = resultStr;
	for (let i = 0; i < arr.length; i++) {
		val += String.fromCharCode(arr[i]);
	}
	return val;
}

let ser = "";
let succeedCallback = ()=>{};
let responseTimeoutTimer = '';//响应超时的定时器

//操作蓝牙 
export const startOperateBluetooth = function(content, type,succeedCallbackFun,failCallback=()=>{},paramValue) {
	succeedCallback = succeedCallbackFun;
	uni.showLoading({
		title: content,
		mask: true
	})
	ser = new Date().getTime();
	let data = getCommandPacket(type, vm.$store.state.deviceData.ecuId,paramValue);
	writeDataToDeviceBySubPackage(vm.$store.state.bluetoothDevice, data);
	responseTimeoutTimer = setTimeout(() => {
		clearTimeout(responseTimeoutTimer);
		if (ser != "") {
			ser = '';
			uni.hideLoading();
			uni.showToast({
				title: "响应超时",
				icon: 'none',
				mask: true
			})
			failCallback();
		}
	}, 6000)
}
//解析报文
export const parsePacket = function(packet) {
	let result = hexToStr(packet);
	console.log(`回复的报文数据-${getNowTime()}`, result);
	//'TBOX,CQCT,0,C012302200001,12.02,01.34,861197063337689,89860428221990213392,10638.0470E,2928.8837N,0,0.00,0,0.00,0,0.0,12.0,0,0.00000,0.0,0.0,0.0,90,0.00000,2,P0562,0.0,0.0,0,0.0,0.0,0,0,00,,,1678343284,32117d11f0859612403a521a61aed531,TBOXEND'
	let arr = result.split(",");
	let resMd5code = arr[arr.length - 2];
	let md5Code = "JDWARQ_mCLLoVQlPHgkixVj";
	let str = arr.slice(0, arr.length - 2).join(",") + "," + md5Code;
	//1、先匹配校验码
	if (resMd5code == md5(str)) {
       //校验成功，则向硬件回复指令
	   
	  let data = stringToHex("TBOX,CQCT,RECEIVED,TBOXEND");
	   writeDataToDeviceBySubPackage(vm.$store.state.bluetoothDevice, data);
	   
		let dataType = arr[2];
		console.log("验证成功=" + dataType);
		if (dataType == 0) { //上报
			vm.$store.commit("setIndexDataPoint", {
				keyStatus: arr[10],
				lastUpFlag: 0,
				engineStatus: arr[11] > 0 ? 1 : 0,
				surplusOil: arr[17],
				insideVoltage: arr[16],
				carFrontTirePressure: arr[26],
				carRearTirePressure: arr[27],
				lockStatus: arr[28],
				carStatus: arr[24],
			});
			
			
			vm.$store.commit("setGuardDataPoint", {
				carStatus:arr[24]
			});

            // console.log("setDrivingDataPoint",resMd5code);
			vm.$store.commit("setDrivingDataPoint", {
				engineTemperature:arr[15],//arr[15]
				currentOil: arr[18],
				engineSpeed: arr[11],
				doorOpen: arr[13],
				driveAverageOil: arr[19],
				carFrontTirePressure: arr[26],
				carRearTirePressure: arr[27],
				createTime: arr[arr.length - 3],
				carSpeed: arr[12]
			});
			
		} else if (dataType == 1005 || dataType == 1006 ||  dataType == 1001 || dataType == 1002) {
			//帧序号相同
			if (ser == arr[4]) {
				clearTimeout(responseTimeoutTimer);
				ser=''; // 找到了，则清空
				console.log("清空ser",ser);
				let flag = true;
				let code = arr[5];
				if (code == 0) {
					flag  = true
				} else {
					flag =  false;
				}
				succeedCallback(flag,dataType)
			}
		}
	}
}


let bluetoothResponsePackage = '';
//开始并且监听特征值的变化
export let notifyAndOnBLECharacteristicValueChange = (device) => {
	//防止没有更换状态
	uni.notifyBLECharacteristicValueChange({
		state: true,
		deviceId: device.deviceId,
		serviceId: SERVICEID,
		characteristicId: NOTIFYID,
		success(res) {
			console.log("开启notify通知模式成功", res);
			uni.onBLECharacteristicValueChange((res) => {
				// console.log("监听特征值", res);
				clearTimeout(notifyTimerId);
				let val = arrayBufferToHexString(res.value);
				//vm.$store.commit("setRespondPackage", val);

				if (val) {
					let start = val.substring(0, 20); //54424F582C435143542C =start
					if (start == "54424F582C435143542C") {
						bluetoothResponsePackage = "";
					}
					bluetoothResponsePackage = bluetoothResponsePackage + val;
					let end = bluetoothResponsePackage.substring(bluetoothResponsePackage.length -
						16); //2C54424F58454E44  =end
					if (end == "2C54424F58454E44") {
						//console.log("监听到的完整报文",bluetoothResponsePackage);
						if (bluetoothResponsePackage.length > 400) { //上报的报文长度484
							parsePacket(bluetoothResponsePackage);
							//蓝牙上报报文
						} else {
							parsePacket(bluetoothResponsePackage, ser);

						}

					}else{
						
						// let temp = hexToStr(bluetoothResponsePackage);
						// console.log(`临时解析报文-${getNowTime()}`, temp);
					}

				}

			})
		},
		fail(res) {
			console.log("开启notify通知模式失败:", BLUETOOTH_MESSAGE[res.errCode]);
		}
	})
}


let writeBLECharacteristicValue = (device, value, isLastPackage = true) => {
	console.log("写入数据", value);
	uni.writeBLECharacteristicValue({
		deviceId: device.deviceId,
		serviceId: SERVICEID,
		characteristicId: WRITEID,
		value,
		success(res) {
			vm.$store.commit("setIsConnected", true);
			console.log("写入数据成功", res);
			//判断是否是最后一包，如果是最后一包，则开启通讯计时器
			if (isLastPackage) {
				notifyTimerId = setTimeout(() => {
					//showModalUtil("蓝牙响应超时")
				}, 4000)
			}
		},
		fail(res) {
			console.log("写入数据失败", BLUETOOTH_MESSAGE[res.errCode]);
			console.log("写入数据失败", res);
			if(res.errCode == "10006"){ //当前连接已断开
				vm.$store.commit("setIsConnected", false);
			}
			//showModalUtil("写入数据失败");
		}

	})
}

export let closeBLEConnection = (device, callback = () => {}) => {
	uni.closeBLEConnection({
		deviceId: device.deviceId,
		success() {
			console.log("关闭蓝牙连接成功");
		},
		fail(res) {
			console.log("关闭蓝牙连接失败", res);

			console.log("关闭蓝牙连接失败", BLUETOOTH_MESSAGE[res.errCode]);
		},
		complete() {
			callback();
		}
	})
}


export let closeBluetoothAdapter = (callback) => {
	return new Promise((resolve, reject) => {
		uni.closeBluetoothAdapter({
			success() {
				console.log("关闭蓝牙适配器成功");
			},
			fail(res) {
				console.log("关闭蓝牙适配器失败：", BLUETOOTH_MESSAGE[res.errCode]);
			},
			complete() {
				callback();
			}
		})
	})
}

//不分包写数据
export let writeDataToDevice = (device, data) => {
	console.log("发送数据", data);
	vm.$store.commit("setRespondPackage", '');

	let allBuffer = hexStringToArrayBuffer(data);
	writeBLECharacteristicValue(device, allBuffer);
}

//分包写数据
export let writeDataToDeviceBySubPackage = (device, data) => {
	vm.$store.commit("setRespondPackage", '');
	let bufferArray = getBufferArrayBy20(data);
	console.log('bufferArray.length', bufferArray.length);
	for (let i = 0; i < bufferArray.length; i++) {
		sleep(1); //同步延迟1ms
		writeBLECharacteristicValue(device, bufferArray[i], i == bufferArray.length - 1);
	}
}


export let getConnectedBluetoothDevices = (callback) => {
	uni.getConnectedBluetoothDevices({
		services: [SERVICEID],
		success(res) {
			console.log("获取连接的蓝牙设备成功", res);
			callback(res.devices)
		},
		fail(res) {
			console.log("获取连接的蓝牙设备失败", res);
			callback([]);
		},
		complete() {

		}
	})

}
